package chapter4;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;

public class Ex8 extends JApplet {
  public static void main(String s[]) {
    JFrame frame = new JFrame();
    frame.setTitle("Julia set");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JApplet applet = new Ex8();
    applet.init();
    frame.getContentPane().add(applet);
    frame.pack();
    frame.setVisible(true);
  }
  
  public void init() {
    JPanel panel = new JuliaPanel();
    getContentPane().add(panel);
  }
}

class JuliaPanel extends JPanel{
  BufferedImage bi;
  float xmin = -2;
  float ymin = -2;
  float xmax = 2;
  float ymax = 2;
  float xscale = 1;
  float yscale = 1;
  int x1, y1, x2, y2;
  
  public JuliaPanel() {
    setPreferredSize(new Dimension(500, 500));
    setBackground(Color.white);
    this.addMouseListener(new MouseAdapter() {
       public void mousePressed(MouseEvent ev) {
         x1 = ev.getX();
         y1 = ev.getY();
       }
       
       public void mouseReleased(MouseEvent ev) {
         x2 = ev.getX();
         y2 = ev.getY();
         xmax = xmin + xscale * x2;
         ymax = ymin + yscale * y2;
         xmin = xmin + xscale * x1;
         ymin = ymin + yscale * y1;
         repaint();
       }
    });
  }
  
  private void createImage() {
    int w = this.getWidth();
    int h = this.getHeight();
    bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    WritableRaster raster = bi.getRaster();
    int[] rgb = new int[3];
    xscale = (xmax-xmin)/w;
    yscale = (ymax-ymin)/h;
    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        float zr = xmin + j * xscale;
        float zi = ymin + i * yscale;
        int count = iterCount(zr, zi);
        rgb[0] = (count & 0x07) << 5;
        rgb[1] = ((count >> 3) & 0x07) << 5;
        rgb[2] = ((count >> 6) & 0x07) << 5;
        raster.setPixel(j, i, rgb);
      }
    }
  }

  private int iterCount(float zr, float zi) {
    int max = 512;
    float cr = -0.672f;
    float ci = 0.435f;
    float lengthsq = 0;
    int count = 0;
    while ((lengthsq < 4.0) && (count < max)) {
      float temp = zr * zr - zi * zi + cr;
      zi = 2 * zr * zi + ci;
      zr = temp;
      lengthsq = zr * zr + zi * zi;
      count++;
    }
    return max-count;
  }

  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    createImage();
    g.drawImage(bi, 0, 0, this);
  }
}